#include "opmysql.h"
using namespace std;

// #define DBHOST "tcp://127.0.0.1:3306"
// #define USER "root"
// #define PASSWORD "123"

// const char *TMP_FILE = "tmp.txt";

#define RELEASE_PTR(ptr)    delete ptr; ptr=nullptr;


 OpMysql::OpMysql(const std::string &host, const std::string &user, const std::string &passwd) {
    db = new DataBaseProperty(host, user, passwd);
    driver = get_driver_instance();
    conn = nullptr;     // 在构造函数里尝试connect有风险，如果构造函数构建失败，逻辑不好处理

    // 初始化 stmt, res
    stmt = nullptr;
    res = nullptr;
}

OpMysql::~OpMysql() {
    if(res != nullptr) { RELEASE_PTR(res);}
    if(stmt != nullptr) { RELEASE_PTR(stmt);}
    if(conn != nullptr)
    {
        if(!(conn->isClosed())) {
            conn->close();
        }
        delete conn; conn = nullptr;
    }
    // sql::Driver 自己管理构析函数
    if(db != nullptr) { RELEASE_PTR(db); }

}


OpState  OpMysql::connect() {
    // 检查当前是否有连接，没有连接才建立连接
    if(this->conn == nullptr)
    {
        if(this->driver != nullptr)
        {
            conn = driver->connect(db->host, db->user, db->passwd);
            if(conn) return CONNECTION_UP;
            else     return CONNECTION_DOWN;
        }else
            return DRIVER_DOWN;
    }
    return CONNECTION_UP;
}

OpState OpMysql::connect(const DataBaseProperty &db)
{
    // 检查当前是否有连接，有连接则关闭
    if(this->conn != nullptr)
    {
        if(!conn->isClosed()) conn->close();
        conn = nullptr;
    }
    // 更新数据库连接属性
    *(this->db) = db;
    
    // 连接，返回连接状态
    return connect();
}

OpState OpMysql::execute(const string &sql)
{
    if(stmt == nullptr) {
        if(conn != nullptr) {
            stmt = conn->createStatement();
            if(stmt == nullptr)
                return CONNECTION_DOWN;
        }else {
            return CONNECTION_DOWN;
        }
    }
    // auto res2{msyql_statement->executeQuery("SELECT 'Welcome to Connector/C++' AS _message")};
    try
    {
        this->stmt->execute(sql);
    }
    catch(const sql::SQLException& e)
    {
        std::cerr << e.what() << '\n';
        return STATEMENT_EROR;
    }
    return STATEMENT_PASS;
}



sql::ResultSet* OpMysql::executeQueue(const std::string &sql)
{
    // 删除旧的查询结果
    if(res != nullptr) { RELEASE_PTR(res);}

    // 属性合法性检查
    if(stmt == nullptr) {
        if(conn != nullptr) {
            stmt = conn->createStatement();
            if(stmt == nullptr)
                return nullptr;
        }else {
            return nullptr;
        }
    }
    try
    {
        res = this->stmt->executeQuery(sql);
    }
    catch(const sql::SQLException& e)
    {
        std::cerr << e.what() << '\n';
        return nullptr;
    }
    return res;
}


void DisplayOpMysql(const OpMysql &op)
{
    cout << "OpMysql Host:" << op.db->host << endl;
    cout << "OpMysql User:" << op.db->user << endl;
}